﻿using System;
using System.Reactive.Subjects;
using System.Reactive.Linq;
using System.Windows.Forms;

namespace Demo
{
	public partial class LinqForm : Form
	{
		private MyObservableClass x;
	    private IDisposable super; 

		public LinqForm()
		{
			InitializeComponent();
			
			x = new MyObservableClass();
			x.CoolThingHappened.Subscribe(thing => listBox1.Items.Add(thing));
			super = x.SuperCoolThingHappened.Subscribe(thing => listBox1.Items.Add(thing + " SuperCool!"));
			x.UniqueThingHappened.Subscribe(thing => listBox1.Items.Add(thing));
		}

		private void button1_Click(object sender, EventArgs e)
		{
			x.MakeCoolThingsHappen();
		}

        private void button2_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            super.Dispose();
        }

	}

	public class MyObservableClass
	{
		//ISubject so we can generate AND consume
		private ISubject<int> coolThingHappened = new Subject<int>();

		//IObservable so can ONLY consume
		public IObservable<int> CoolThingHappened
		{
			get { return coolThingHappened; }
		}

		//add important info collection/generation/processing here
		public void MakeCoolThingsHappen()
		{
			coolThingHappened.OnNext(1);
			coolThingHappened.OnNext(2);
			coolThingHappened.OnNext(3);
			coolThingHappened.OnNext(4);
			coolThingHappened.OnNext(5);
			coolThingHappened.OnNext(6);
			coolThingHappened.OnNext(7);
			coolThingHappened.OnNext(8);
			coolThingHappened.OnNext(9);
		}

		//Observables are composable
		public IObservable<int> SuperCoolThingHappened
		{
			get
			{
				//this localizes the logic in the class, not the subscriber(s)
				return coolThingHappened
					.Where(x => x > 5);
			}
		}

	
		private bool hasHappened = false;
		public IObservable<string> UniqueThingHappened
		{
			get
			{
				return SuperCoolThingHappened
					.Where(x => (x > 7) && !hasHappened)  //can access outside var
					.Do(x => hasHappened = true)
					.Select (s => "Unique Thing Happened!");  //can transform type
			}
		}

	}

}